/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace DaveSexton.DocProject
{
	public class MarshalByRefEnumerator<T> : MarshalByRefObject, IEnumerator<T>
	{
		#region Public Properties
		[System.Diagnostics.DebuggerHidden]
		public virtual T Current
		{
			get
			{
				return enumerator.Current;
			}
		}

		[System.Diagnostics.DebuggerHidden]
		object System.Collections.IEnumerator.Current
		{
			get
			{
				return enumerator.Current;
			}
		}
		#endregion

		#region Private / Protected
		private readonly IEnumerator<T> enumerator;
		private readonly object lifetimeService;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(EnumerableBuilder<T> builder)
		{
			if (builder == null)
				throw new ArgumentNullException("builder");

			IEnumerable<T> enumerable = builder();

			if (enumerable == null)
				throw new InvalidOperationException("The specified builder returned a null reference.");

			enumerator = enumerable.GetEnumerator();
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(object lifetimeService, EnumerableBuilder<T> builder)
		{
			if (builder == null)
				throw new ArgumentNullException("builder");

			IEnumerable<T> enumerable = builder();

			if (enumerable == null)
				throw new InvalidOperationException("The specified builder returned a null reference.");

			enumerator = enumerable.GetEnumerator();
			this.lifetimeService = lifetimeService;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(IEnumerable<T> enumerable)
		{
			if (enumerable == null)
				throw new ArgumentNullException("enumerable");

			enumerator = enumerable.GetEnumerator();
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(object lifetimeService, IEnumerable<T> enumerable)
		{
			if (enumerable == null)
				throw new ArgumentNullException("enumerable");

			enumerator = enumerable.GetEnumerator();
			this.lifetimeService = lifetimeService;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(params T[] items)
		{
			if (items == null)
				throw new ArgumentNullException("items");

			enumerator = new List<T>(items).GetEnumerator();
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		[System.Diagnostics.DebuggerHidden]
		public MarshalByRefEnumerator(object lifetimeService, params T[] items)
		{
			if (items == null)
				throw new ArgumentNullException("items");

			enumerator = new List<T>(items).GetEnumerator();
			this.lifetimeService = lifetimeService;
		}
		#endregion

		#region Methods
		[System.Diagnostics.DebuggerHidden]
		[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand,
			Flags = System.Security.Permissions.SecurityPermissionFlag.Infrastructure)]
		public override object InitializeLifetimeService()
		{
			return lifetimeService;
		}

		[System.Diagnostics.DebuggerHidden]
		public virtual bool MoveNext()
		{
			return enumerator.MoveNext();
		}

		[System.Diagnostics.DebuggerHidden]
		public virtual void Reset()
		{
			enumerator.Reset();
		}

		/// <summary>
		/// Releases all resources used by an instance of the <see cref="MarshalByRefEnumerator" /> class.
		/// </summary>
		/// <remarks>
		/// This method calls the virtual <see cref="Dispose(bool)" /> method, passing in <strong>true</strong>, and then suppresses 
		/// finalization of the instance.
		/// </remarks>
		[System.Diagnostics.DebuggerHidden]
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Releases unmanaged resources before an instance of the <see cref="MarshalByRefEnumerator" /> class is reclaimed by garbage collection.
		/// </summary>
		/// <remarks>
		/// This method releases unmanaged resources by calling the virtual <see cref="Dispose(bool)" /> method, passing in <strong>false</strong>.
		/// </remarks>
		[System.Diagnostics.DebuggerHidden]
		~MarshalByRefEnumerator()
		{
			Dispose(false);
		}

		/// <summary>
		/// Releases the unmanaged resources used by an instance of the <see cref="MarshalByRefEnumerator" /> class and optionally releases the managed resources.
		/// </summary>
		/// <param name="disposing"><strong>true</strong> to release both managed and unmanaged resources; <strong>false</strong> to release only unmanaged resources.</param>
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
				enumerator.Dispose();
		}
		#endregion
	}
}
